<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <script>
    /* 
      https://github.com/lf2021/Front-End-Interview/blob/master/08.%E9%9D%A2%E8%AF%95%E9%AB%98%E9%A2%91%E6%89%8B%E6%92%95%E4%BB%A3%E7%A0%81%E9%A2%98/%E9%9D%A2%E8%AF%95%E9%AB%98%E9%A2%91%E6%89%8B%E6%92%95%E4%BB%A3%E7%A0%81%E9%A2%98.md#%E6%89%8B%E5%86%99%E4%B8%80%E4%B8%AA%E5%8F%91%E5%B8%83%E8%AE%A2%E9%98%85%E6%A8%A1%E5%BC%8F
     */
    // 发布订阅模式
    class EventEmitter {
      constructor() {
        // 事件对象，存放订阅的名字和事件
        this.events = {}
      }
      // 订阅事件的方法
      on(eventName, callback) {
        if (!this.events[eventName]) {
          // 注意是数据，一个名字可以订阅多个事件函数
          this.events[eventName] = [callback]
        } else {
          // 存在则push到指定数组的尾部保存
          this.events[eventName].push(callback)
        }
      }
      // 触发事件的方法
      emit(eventName) {
        // 遍历执行所有订阅的事件
        this.events[eventName] && this.events[eventName].forEach((cb) => cb())
      }
      // 移除订阅事件
      removeListener(eventName, callback) {
        if (this.events[eventName]) {
          this.events[eventName] = this.events[eventName].filter(
            (cb) => cb != callback
          )
        }
      }
      // 只执行一次订阅的事件，然后移除
      once(eventName, callback) {
        // 绑定的时fn, 执行的时候会触发fn函数
        let fn = () => {
          callback() // fn函数中调用原有的callback
          this.removeListener(eventName, fn) // 删除fn, 再次执行的时候之后执行一次
        }
        this.on(eventName, fn)
      }
    }

    // test
    let em = new EventEmitter();
    let workday = 0;
    em.on("work", function () {
      workday++;
      console.log("work everyday");
    });

    em.once("love", function () {
      console.log("just love you");
    });

    function makeMoney() {
      console.log("make one million money");
    }
    em.on("money", makeMoney)；

    let time = setInterval(() => {
      em.emit("work");
      em.removeListener("money", makeMoney);
      em.emit("money");
      em.emit("love");
      if (workday === 5) {
        console.log("have a rest")
        clearInterval(time);
      }
    }, 1);

    //  输出
    //  work everyday
    //  just love you
    //  work everyday
    //  work everyday
    //  work everyday
    //  work everyday
    //  have a rest
  </script>
</body>

</html>